{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A tour of MLJ\n",
    "\n",
    "### Models, machines, basic training and testing\n",
    "\n",
    "Let's load data and define train and test rows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "using MLJ\n",
    "using DataFrames, Statistics\n",
    "\n",
    "Xraw = rand(300,3)\n",
    "y = exp(Xraw[:,1] - Xraw[:,2] - 2Xraw[:,3] + 0.1*rand(300))\n",
    "X = DataFrame(Xraw)\n",
    "\n",
    "train, test = partition(eachindex(y), 0.70); # 70:30 split"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A *model* is a container for hyperparameters:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNNRegressor(target_type = Float64,\n",
       "             K = 10,\n",
       "             metric = MLJ.KNN.euclidean,\n",
       "             kernel = MLJ.KNN.reciprocal,)\u001b[0m\u001b[1m @ 2…26\u001b[22m"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn_model=KNNRegressor(K=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Wrapping the model in data creates a *machine* which will store training outcomes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0m\u001b[1mMachine @ 2…86\u001b[22m\n"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn = machine(knn_model, X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Training on the training rows and evaluating on the test rows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Training \u001b[0m\u001b[1mMachine @ 2…86\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.12853140928320453"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fit!(knn, rows=train)\n",
    "yhat = predict(knn, X[test,:])\n",
    "rms(yhat, y[test])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or, we could have skipped the train/test definitions and evaluated one line:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Evaluating using a holdout set. \n",
      "│ fraction_train=0.7 \n",
      "│ shuffle=false \n",
      "│ measure=MLJ.rms \n",
      "│ operation=StatsBase.predict \n",
      "│ Resampling from all rows. \n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/resampling.jl:91\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.12853140928320453"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "evaluate!(knn, resampling=Holdout(fraction_train=0.7), measure=rms)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Our machine/model constructions and associateed fit/predict syntax anticipates a powerful extension for building networks of learners described later. Changing a hyperparameter and re-evaluating:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Evaluating using a holdout set. \n",
      "│ fraction_train=0.7 \n",
      "│ shuffle=false \n",
      "│ measure=MLJ.rms \n",
      "│ operation=StatsBase.predict \n",
      "│ Resampling from all rows. \n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/resampling.jl:91\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.15618555765353453"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn_model.K = 20\n",
    "evaluate!(knn, resampling=Holdout(fraction_train=0.7))  # `default_measure(knn) == rms` so `measure` kwarg can be dropped"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Homogeneous ensembles"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here's a bagged ensemble model for 20 K-nearest neighbour regressors:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MLJ.DeterministicEnsembleModel(atom = \u001b[0m\u001b[1mKNNRegressor @ 2…26\u001b[22m,\n",
       "                               weights = Float64[],\n",
       "                               bagging_fraction = 0.8,\n",
       "                               rng = MersenneTwister(UInt32[0x3e5b42d3, 0xc66a5ccd, 0x57ccde19, 0x1bbc369f]),\n",
       "                               n = 20,\n",
       "                               parallel = true,\n",
       "                               out_of_bag_measure = Any[],)\u001b[0m\u001b[1m @ 9…05\u001b[22m"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ensemble_model = EnsembleModel(atom=knn_model, n=20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MLJ.DeterministicEnsembleModel(atom = KNNRegressor(target_type = Float64,\n",
      "                                                   K = 20,\n",
      "                                                   metric = MLJ.KNN.euclidean,\n",
      "                                                   kernel = MLJ.KNN.reciprocal,),\n",
      "                               weights = Float64[],\n",
      "                               bagging_fraction = 0.8,\n",
      "                               rng = MersenneTwister(UInt32[0x3e5b42d3, 0xc66a5ccd, 0x57ccde19, 0x1bbc369f]),\n",
      "                               n = 20,\n",
      "                               parallel = true,\n",
      "                               out_of_bag_measure = Any[],)\u001b[0m\u001b[1m @ 9…05\u001b[22m"
     ]
    }
   ],
   "source": [
    "@more"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It can be trained and tested the same as any other model:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Evaluating using cross-validation. \n",
      "│ nfolds=6. \n",
      "│ shuffle=false \n",
      "│ measure=MLJ.rms \n",
      "│ operation=StatsBase.predict \n",
      "│ Resampling from all rows. \n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/resampling.jl:135\n",
      "\u001b[33mCross-validating: 100%[=========================] Time: 0:00:04\u001b[39m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "6-element Array{Float64,1}:\n",
       " 0.1540634261614765  \n",
       " 0.06131594097434255 \n",
       " 0.12431277342613434 \n",
       " 0.056901727300418634\n",
       " 0.1129447261633142  \n",
       " 0.16218266101438011 "
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ensemble = machine(ensemble_model, X, y)\n",
    "estimates = evaluate!(ensemble, resampling=CV())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.11195354250667773"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mean(estimates)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Systematic tuning"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's simultaneously tune the ensemble's `bagging_fraction` and the K-nearest neighbour hyperparameter `K`. Since one of our models is a field of the other, we have nested hyperparameters:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(atom = (target_type = Float64,\n",
       "         K = 20,\n",
       "         metric = MLJ.KNN.euclidean,\n",
       "         kernel = MLJ.KNN.reciprocal,),\n",
       " weights = Float64[],\n",
       " bagging_fraction = 0.8,\n",
       " rng = MersenneTwister(UInt32[0x3e5b42d3, 0xc66a5ccd, 0x57ccde19, 0x1bbc369f]),\n",
       " n = 20,\n",
       " parallel = true,\n",
       " out_of_bag_measure = Any[],)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params(ensemble_model) # extract model hyperparameters as nested named tuple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To define a tuning grid, we construct ranges for the two parameters and collate these ranges following the same pattern above (omitting parameters that don't change):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(atom = (K = \u001b[0m\u001b[1mNumericRange{K} @ 1…42\u001b[22m,),\n",
       " bagging_fraction = \u001b[0m\u001b[1mNumericRange{bagging_fraction} @ 3…05\u001b[22m,)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B_range = range(ensemble_model, :bagging_fraction, lower= 0.5, upper=1.0, scale = :linear)\n",
    "K_range = range(knn_model, :K, lower=1, upper=100, scale=:log10)\n",
    "nested_ranges = (atom = (K = K_range,), \n",
    "                 bagging_fraction = B_range)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we choose a tuning strategy:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Grid(resolution = 12,\n",
       "     parallel = true,)\u001b[0m\u001b[1m @ 8…22\u001b[22m"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuning = Grid(resolution=12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And a resampling strategy:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Holdout(fraction_train = 0.8,\n",
       "        shuffle = false,)\u001b[0m\u001b[1m @ 1…81\u001b[22m"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "resampling = Holdout(fraction_train=0.8)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And define a new model which wraps the these strategies around our ensemble model:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MLJ.DeterministicTunedModel(model = \u001b[0m\u001b[1mDeterministicEnsembleModel @ 9…05\u001b[22m,\n",
       "                            tuning = \u001b[0m\u001b[1mGrid @ 8…22\u001b[22m,\n",
       "                            resampling = \u001b[0m\u001b[1mHoldout @ 1…81\u001b[22m,\n",
       "                            measure = nothing,\n",
       "                            operation = StatsBase.predict,\n",
       "                            nested_ranges = (atom = (K = \u001b[0m\u001b[1mNumericRange{K} @ 1…42\u001b[22m,), bagging_fraction = \u001b[0m\u001b[1mNumericRange{bagging_fraction} @ 3…05\u001b[22m),\n",
       "                            minimize = true,\n",
       "                            full_report = true,)\u001b[0m\u001b[1m @ 8…06\u001b[22m"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuned_ensemble_model = TunedModel(model=ensemble_model, \n",
    "    tuning=tuning, resampling=resampling, nested_ranges=nested_ranges)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fitting the corresponding machine tunes the underlying model (in this case an ensemble) and retrains on all supplied data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Warning: No measure specified. Using measure=MLJ.rms. \n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:104\n",
      "┌ Info: Training \u001b[0m\u001b[1mMachine @ 1…58\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n",
      "\u001b[33mIterating over a 132-point grid: 100%[=========================] Time: 0:00:06\u001b[39m\n",
      "┌ Info: Training best model on all supplied data.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/tuning.jl:179\n"
     ]
    }
   ],
   "source": [
    "tuned_ensemble = machine(tuned_ensemble_model, X[train,:], y[train])\n",
    "fit!(tuned_ensemble);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For each fitted machine, one may inspect a user-friendly version of the fitted parameters (as opposed to the hyperparameters stored in its model). In the current case this is the best ensemble model (trained on all available data):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(best_model = \u001b[0m\u001b[1mDeterministicEnsembleModel @ 3…07\u001b[22m,)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fitted_params(tuned_ensemble)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(atom = (target_type = Float64,\n",
       "         K = 4,\n",
       "         metric = MLJ.KNN.euclidean,\n",
       "         kernel = MLJ.KNN.reciprocal,),\n",
       " weights = Float64[],\n",
       " bagging_fraction = 0.8636363636363636,\n",
       " rng = MersenneTwister(UInt32[0x3e5b42d3, 0xc66a5ccd, 0x57ccde19, 0x1bbc369f]),\n",
       " n = 20,\n",
       " parallel = true,\n",
       " out_of_bag_measure = Any[],)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ans.best_model |> params"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `report` method gives more detail on the tuning process:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(parameter_names = [\"atom.K\" \"bagging_fraction\"],\n",
       " parameter_scales = Symbol[:log10 :linear],\n",
       " parameter_values = Any[1 0.5; 2 0.5; … ; 66 1.0; 100 1.0],\n",
       " measurements = [0.0718745, 0.0660446, 0.06871, 0.071838, 0.0702845, 0.0755318, 0.0827372, 0.101599, 0.125313, 0.16274  …  0.070628, 0.065686, 0.0660806, 0.0689687, 0.0723638, 0.0714392, 0.074366, 0.0877627, 0.108137, 0.137101],\n",
       " best_measurement = 0.06467637213165063,)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "report(tuned_ensemble) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or for a plot of tuning results:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Recompiling stale cache file /Users/anthony/.julia/compiled/v1.1/Plots/ld3vC.ji for Plots [91a5bcdd-55d7-5caf-9e0b-520d859cae80]\n",
      "└ @ Base loading.jl:1184\n",
      "┌ Info: Recompiling stale cache file /Users/anthony/.julia/compiled/v1.1/PyPlot/oatAj.ji for PyPlot [d330b81b-6aea-500a-939a-2ce795aea3ee]\n",
      "└ @ Base loading.jl:1184\n",
      "┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.\"s\"` instead of `o[\"s\"]`.\n",
      "│   caller = top-level scope at none:0\n",
      "└ @ Core none:0\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:935\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:935\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:937\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:937\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:938\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:938\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:939\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:939\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:942\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:942\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:942\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:942\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = py_init_subplot(::Plots.Plot{Plots.PyPlotBackend}, ::Plots.Subplot{Plots.PyPlotBackend}) at pyplot.jl:342\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:342\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_add_series(::Plots.Plot{Plots.PyPlotBackend}, ::Plots.Series) at pyplot.jl:592\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:592\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:999\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:999\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1007\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1007\n",
      "┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.\"s\"` instead of `o[\"s\"]`.\n",
      "│   caller = py_colormap(::ColorGradient) at pyplot.jl:67\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:67\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_colormap(::ColorGradient) at pyplot.jl:67\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:67\n",
      "┌ Warning: `getindex(c::ColorMap, x)` is deprecated, use `getproperty(c, x)` instead.\n",
      "│   caller = py_colormap(::ColorGradient) at pyplot.jl:68\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:68\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1008\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1008\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1015\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1015\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1016\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1016\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1017\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1017\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1018\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1018\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1018\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1018\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1018\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1018\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1019\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1019\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1020\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1020\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1021\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1021\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1029\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1029\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1029\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1029\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1030\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1030\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1030\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1030\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1038\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1038\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1038\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1038\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1039\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1039\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1039\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1039\n",
      "┌ Warning: `haskey(o::PyObject, s::Union{Symbol, AbstractString})` is deprecated, use `hasproperty(o, s)` instead.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1058\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1058\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1060\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1060\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_scale(::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:894\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:894\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_lims(::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:844\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:844\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_ticks(::PyCall.PyObject, ::Tuple{Array{Float64,1},Array{LaTeXStrings.LaTeXString,1}}, ::Symbol) at pyplot.jl:849\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:849\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_ticks(::PyCall.PyObject, ::Tuple{Array{Float64,1},Array{LaTeXStrings.LaTeXString,1}}, ::Symbol) at pyplot.jl:863\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:863\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_ticks(::PyCall.PyObject, ::Tuple{Array{Float64,1},Array{LaTeXStrings.LaTeXString,1}}, ::Symbol) at pyplot.jl:864\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:864\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1081\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1081\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1082\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1082\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1086\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1086\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1086\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1086\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1087\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1087\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1087\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1087\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1088\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1088\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1089\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1089\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1090\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1090\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1091\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1091\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1095\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1095\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1100\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1100\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_axis_colors(::Plots.Subplot{Plots.PyPlotBackend}, ::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:914\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:914\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_axis_colors(::Plots.Subplot{Plots.PyPlotBackend}, ::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:915\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:915\n",
      "┌ Warning: `haskey(o::PyObject, s::Union{Symbol, AbstractString})` is deprecated, use `hasproperty(o, s)` instead.\n",
      "│   caller = py_set_axis_colors(::Plots.Subplot{Plots.PyPlotBackend}, ::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:918\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:918\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_axis_colors(::Plots.Subplot{Plots.PyPlotBackend}, ::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:920\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:920\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_axis_colors(::Plots.Subplot{Plots.PyPlotBackend}, ::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:923\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:923\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_axis_colors(::Plots.Subplot{Plots.PyPlotBackend}, ::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:923\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:923\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_axis_colors(::Plots.Subplot{Plots.PyPlotBackend}, ::PyCall.PyObject, ::Plots.Axis) at pyplot.jl:923\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:923\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_ticks(::PyCall.PyObject, ::Tuple{Array{Float64,1},Array{String,1}}, ::Symbol) at pyplot.jl:849\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:849\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_ticks(::PyCall.PyObject, ::Tuple{Array{Float64,1},Array{String,1}}, ::Symbol) at pyplot.jl:863\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:863\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_set_ticks(::PyCall.PyObject, ::Tuple{Array{Float64,1},Array{String,1}}, ::Symbol) at pyplot.jl:864\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:864\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _before_layout_calcs(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1148\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1148\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = py_drawfig(::PyPlot.Figure) at pyplot.jl:257\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:257\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = py_canvas at pyplot.jl:251 [inlined]\n",
      "└ @ Core /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:251\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_renderer(::PyPlot.Figure) at pyplot.jl:254\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:254\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_bbox(::PyCall.PyObject) at pyplot.jl:266\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:266\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = py_extents(::PyPlot.Figure) at pyplot.jl:261\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:261\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_extents(::PyPlot.Figure) at pyplot.jl:261\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:261\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_extents(::PyCall.PyObject) at pyplot.jl:261\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:261\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_extents(::PyCall.PyObject) at pyplot.jl:261\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:261\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_bbox_ticks(::PyCall.PyObject, ::String) at pyplot.jl:282\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:282\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_bbox_axislabel(::PyCall.PyObject, ::String) at pyplot.jl:288\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:288\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_bbox_axislabel(::PyCall.PyObject, ::String) at pyplot.jl:288\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:288\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_bbox_title(::PyCall.PyObject) at pyplot.jl:304\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:304\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_bbox_title(::PyCall.PyObject) at pyplot.jl:304\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:304\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = py_bbox_title(::PyCall.PyObject) at pyplot.jl:304\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:304\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _update_min_padding!(::Plots.Subplot{Plots.PyPlotBackend}) at pyplot.jl:1184\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1184\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _update_min_padding!(::Plots.Subplot{Plots.PyPlotBackend}) at pyplot.jl:1184\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1184\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _update_plot_object(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1304\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1304\n"
     ]
    },
    {
     "data": {
      "image/png": "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hBDioaQoCidPnmT//v1kZ2erHadI169fJ7xefbp3784XcxcxY9qH1KxZk8jISLWj5VMUhf79+uOa58SAMl2p4lQBreb2r2V7rT313cLoX+YFLvwZw9tvv231fHv27OHEqVMMqhCIthjF1R3dgwJwsbNjwYIFDxbA7PFXefIUobVlZmbS7JlmdO/enXHjxlGrVi02bNigdiybcezYMSZMmMC8efMwGm1ngKAtyMzMJC4urlTOnZuba7nBoFaWnJzMl19+ye7du9WOUqQlS5YQEhJKhQoVWblypdpxzLJo0SKaN2/BwIEDuXHjhtpx8plMJvr160fNmjV58sknqVGjJpcuXVI71l0NHz6CP8/EUMehM3X13ahv14tgu/pMmTKFrVu3qh0PgH379nH02FFaujXGQWt/13187byp7xTG1wu/Ij093ar5FkRFEeruRmMfL7OOc9breCHAjy+ioh7r3ymPRYE1Z84cDh46hJdjGH7OjdEpbkREDERRFLWjqS4xMZGmTZvy2WczGTlyJP/973/VjmQzEhISCA2tQHBwMFOnTrXoufft24e3tzflypXj/PnzFj13aTMajTz99NMMGTKE5s2bs379erUjFXLixAn69x/Alcs3iI9L5KWXXuLcuXNqxyqWnTt3EhERwZ5f9rN48bf069dP7Uj5Vq5cybfffouLfQjuDlW5HJ/AK6+8onasQq5fv87GjRsor6mLm84PAK1GR5C+Lu52viyIesCWFQvZuHEjHg5uVHK890D2ui7VSMtIZ9euXVZKdtupEydo6OFmVuvVHY28PUlMTiY5ObnkAUx5JdtsxGNRYMXGxmJv54K9zh2NRoe9zodbt26SkZGhdjTVnTp16vZfRYobGo0de/fuVTuSzdi/fz+JidcBWLVqlUXPvWnTJjIyMkhKSuKnn36y6LlL282bNzl16hQajRM6nZ6dO3eqHamQkydPoigm7PV+2OvKYDKZHpqhAYcPH0aj0WCvLwuKE4cORasdKd+ff/6Jnd4BB50PdjpXNIoLZ86cVTtWIQkJCZhMJly1PgVe12g0OJm8uHjRNlrdUlNTcdE533dsk6vOOX9/a0pPT8dJV7IywVmvyz9HiZlMfy34bM5mKvn1LOyxKLDq1q1Ldk4aWYZrGIzp5JiuERwcgouLi9rRVFevXj0CA4PIMyajKAa6deumdiSb0apV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"
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _update_plot_object(::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1314\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1314\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = _show(::Base64.Base64EncodePipe, ::MIME{Symbol(\"image/png\")}, ::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1343\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1343\n",
      "┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.\n",
      "│   caller = _show(::Base64.Base64EncodePipe, ::MIME{Symbol(\"image/png\")}, ::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1343\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1343\n",
      "┌ Warning: `getindex(f::Figure, x)` is deprecated, use `getproperty(f, x)` instead.\n",
      "│   caller = _show(::Base64.Base64EncodePipe, ::MIME{Symbol(\"image/png\")}, ::Plots.Plot{Plots.PyPlotBackend}) at pyplot.jl:1343\n",
      "└ @ Plots /Users/anthony/.julia/packages/Plots/gylTh/src/backends/pyplot.jl:1343\n"
     ]
    }
   ],
   "source": [
    "using Plots\n",
    "pyplot()\n",
    "plot(tuned_ensemble)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Evaluating the model:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.09603018481782859"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "yhat = predict(tuned_ensemble, X[test,:])\n",
    "rms(yhat, y[test])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or, using all the data, get cross-validation estimates, with cv-tuning on each fold complement (nested resampling):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Evaluating using cross-validation. \n",
      "│ nfolds=4. \n",
      "│ shuffle=false \n",
      "│ measure=MLJ.rms \n",
      "│ operation=StatsBase.predict \n",
      "│ Resampling from all rows. \n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/resampling.jl:135\n",
      "\u001b[33mCross-validating:  20%[=====>                   ]  ETA: 0:00:00\u001b[39m┌ Info: Training \u001b[0m\u001b[1mMachine @ 8…55\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n",
      "\u001b[33mIterating over a 132-point grid: 100%[=========================] Time: 0:00:07\u001b[39m\n",
      "┌ Info: Training best model on all supplied data.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/tuning.jl:179\n",
      "\u001b[33mCross-validating:  40%[==========>              ]  ETA: 0:00:14\u001b[39m┌ Info: Training \u001b[0m\u001b[1mMachine @ 8…55\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n",
      "\u001b[33mIterating over a 132-point grid: 100%[=========================] Time: 0:00:06\u001b[39m\n",
      "┌ Info: Training best model on all supplied data.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/tuning.jl:179\n",
      "\u001b[33mCross-validating:  60%[===============>         ]  ETA: 0:00:10\u001b[39m┌ Info: Training \u001b[0m\u001b[1mMachine @ 8…55\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n",
      "\u001b[33mIterating over a 132-point grid: 100%[=========================] Time: 0:00:05\u001b[39m\n",
      "┌ Info: Training best model on all supplied data.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/tuning.jl:179\n",
      "\u001b[33mCross-validating:  80%[====================>    ]  ETA: 0:00:05\u001b[39m┌ Info: Training \u001b[0m\u001b[1mMachine @ 8…55\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n",
      "\u001b[33mIterating over a 132-point grid: 100%[=========================] Time: 0:00:05\u001b[39m\n",
      "┌ Info: Training best model on all supplied data.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/tuning.jl:179\n",
      "\u001b[33mCross-validating: 100%[=========================] Time: 0:00:26\u001b[39m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "4-element Array{Float64,1}:\n",
       " 0.0995783460072341 \n",
       " 0.07730920590113027\n",
       " 0.05052575931419724\n",
       " 0.10821286146187001"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuned_ensemble = machine(tuned_ensemble_model, X, y)\n",
    "estimates = evaluate!(tuned_ensemble, resampling=CV(nfolds=4), verbosity=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0839065431711079"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mean(estimates)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Learning networks"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "MLJ has a flexible interface for building networks from multiple machine learning elements, whose complexity extend beyond linear \"pipelines\", and with a minimal of added abstraction.\n",
    "\n",
    "In MLJ, a *learning network* is a graph whose nodes apply an operation, such as `predict` or `transform`, using a fixed machine (requiring training) - or which, alternatively, applies a regular (untrained) mathematical operation to its input(s). In practice, a learning network works with *fixed* sources for its training/evaluation data, but can be built and tested in stages. By contrast, an *exported learning network* is a learning network exported as a stand-alone, re-usable `Model` object, to which all the MLJ `Model`  meta-algorthims can be applied (ensembling, systematic tuning, etc). \n",
    "\n",
    "As we shall see, exporting a learning network as a reusable model, is very easy. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Building a simple learning network\n",
    "\n",
    "![](wrapped_ridge.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The diagram above depicts a learning network which standardises the input data, `X`, learns an optimal Box-Cox transformation for the target, `y`, predicts new targets using ridge regression, and then inverse-transforms those predictions (for later comparison with the original test data). The machines are labelled yellow. \n",
    "\n",
    "To implement the network, we begin by loading all data needed for training and evaluation into *source nodes*:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0m\u001b[1mSource @ 2…36\u001b[22m"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Xs = source(X)\n",
    "ys = source(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We label nodes according to their outputs in the diagram. Notice that the nodes `z` and `yhat` use the same machine `box` for different operations. \n",
    "\n",
    "To construct the `W` node we first need to define the machine `stand` that it will use to transform inputs. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0m\u001b[1mNodalMachine @ 2…49\u001b[22m = machine(\u001b[0m\u001b[1mStandardizer @ 1…68\u001b[22m, \u001b[0m\u001b[1m7…17\u001b[22m)"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stand_model = Standardizer()\n",
    "stand = machine(stand_model, Xs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because `Xs` is a node, instead of concrete data, we can call `transform` on the machine without first training it, and the result is the new node `W`, instead of concrete transformed data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0m\u001b[1mNode @ 4…24\u001b[22m = transform(\u001b[0m\u001b[1m2…49\u001b[22m, \u001b[0m\u001b[1m7…17\u001b[22m)"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "W = transform(stand, Xs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To get actual transformed data we *call* the node appropriately, which will require we first train the node. Training a node, rather than a machine, triggers training of *all* necessary machines in the network."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Training \u001b[0m\u001b[1mNodalMachine @ 2…49\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table class=\"data-frame\"><thead><tr><th></th><th>x1</th><th>x2</th><th>x3</th></tr><tr><th></th><th>Float64</th><th>Float64</th><th>Float64</th></tr></thead><tbody><p>2 rows × 3 columns</p><tr><th>1</th><td>-1.24961</td><td>1.30371</td><td>-0.533965</td></tr><tr><th>2</th><td>1.02076</td><td>0.60203</td><td>0.213067</td></tr></tbody></table>"
      ],
      "text/latex": [
       "\\begin{tabular}{r|ccc}\n",
       "\t& x1 & x2 & x3\\\\\n",
       "\t\\hline\n",
       "\t& Float64 & Float64 & Float64\\\\\n",
       "\t\\hline\n",
       "\t1 & -1.24961 & 1.30371 & -0.533965 \\\\\n",
       "\t2 & 1.02076 & 0.60203 & 0.213067 \\\\\n",
       "\\end{tabular}\n"
      ],
      "text/plain": [
       "2×3 DataFrame\n",
       "│ Row │ x1       │ x2      │ x3        │\n",
       "│     │ \u001b[90mFloat64\u001b[39m  │ \u001b[90mFloat64\u001b[39m │ \u001b[90mFloat64\u001b[39m   │\n",
       "├─────┼──────────┼─────────┼───────────┤\n",
       "│ 1   │ -1.24961 │ 1.30371 │ -0.533965 │\n",
       "│ 2   │ 1.02076  │ 0.60203 │ 0.213067  │"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fit!(W, rows=train)\n",
    "W()          # transform all data\n",
    "W(rows=test) # transform only test data\n",
    "W(X[3:4,:])  # transform any data, new or old"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you like, you can think of `W` (and the other nodes we will define) as \"dynamic data\": `W` is *data*, in the sense that  it an be called (\"indexed\") on rows, but *dynamic*, in the sense the result depends on the outcome of training events. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The other nodes of our network are defined similarly:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0m\u001b[1mNode @ 9…05\u001b[22m = inverse_transform(\u001b[0m\u001b[1m1…17\u001b[22m, predict(\u001b[0m\u001b[1m1…17\u001b[22m, transform(\u001b[0m\u001b[1m2…49\u001b[22m, \u001b[0m\u001b[1m7…17\u001b[22m)))"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "box_model = UnivariateBoxCoxTransformer()  # for making data look normally-distributed\n",
    "box = machine(box_model, ys)\n",
    "z = transform(box, ys)\n",
    "\n",
    "ridge_model = RidgeRegressor(lambda=0.1)\n",
    "ridge =machine(ridge_model, W, z)\n",
    "zhat = predict(ridge, W)\n",
    "\n",
    "yhat = inverse_transform(box, zhat)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We are ready to train and evaluate the completed network. Notice that the standardizer, `stand`, is *not* retrained, as MLJ remembers that it was trained earlier:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Not retraining \u001b[0m\u001b[1mNodalMachine @ 2…49\u001b[22m. It is up-to-date.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/networks.jl:227\n",
      "┌ Info: Training \u001b[0m\u001b[1mNodalMachine @ 1…17\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n",
      "┌ Info: Training \u001b[0m\u001b[1mNodalMachine @ 1…17\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:115\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.032194107826598484"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fit!(yhat, rows=train)\n",
    "rms(y[test], yhat(rows=test)) # evaluate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2-element Array{Float64,1}:\n",
       " 0.2691825421997118\n",
       " 0.4059330121685908"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "yhat(X[3:4,:])  # predict on new or old data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can change hyperparameters and retrain:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "┌ Info: Not retraining \u001b[0m\u001b[1mNodalMachine @ 1…17\u001b[22m. It is up-to-date.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/networks.jl:227\n",
      "┌ Info: Not retraining \u001b[0m\u001b[1mNodalMachine @ 2…49\u001b[22m. It is up-to-date.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/networks.jl:227\n",
      "┌ Info: Updating \u001b[0m\u001b[1mNodalMachine @ 1…17\u001b[22m.\n",
      "└ @ MLJ /Users/anthony/Dropbox/Julia7/MLJ/MLJ/src/machines.jl:119\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.03196157940327022"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ridge_model.lambda = 0.01\n",
    "fit!(yhat, rows=train) \n",
    "rms(y[test], yhat(rows=test))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> **Notable feature.** The machine, `ridge::NodalMachine{RidgeRegressor}`, is retrained, because its underlying model has been mutated. However, since the outcome of this training has no effect on the training inputs of the machines `stand` and `box`, these transformers are left untouched. (During construction, each node and machine in a learning network determines and records all machines on which it depends.) This behaviour, which extends to exported learning networks, means we can tune our wrapped regressor without re-computing transformations each time the hyperparameter is changed. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exporting a learning network as a composite model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To export a learning network:\n",
    "- Define a new `mutable struct` model type.\n",
    "- Wrap the learning network code in a model `fit` method.\n",
    "\n",
    "All learning networks that make determinisic (or, probabilistic) predictions export as models of subtype `Deterministic{Node}` (respectively, `Probabilistic{Node}`):\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "mutable struct WrappedRidge <: Deterministic{Node}\n",
    "    ridge_model\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now satisfied that our wrapped Ridge Regression learning network works, we simply cut and paste its defining code into a `fit` method: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "function MLJ.fit(model::WrappedRidge, X, y)\n",
    "    Xs = source(X)\n",
    "    ys = source(y)\n",
    "\n",
    "    stand_model = Standardizer()\n",
    "    stand = machine(stand_model, Xs)\n",
    "    W = transform(stand, Xs)\n",
    "\n",
    "    box_model = UnivariateBoxCoxTransformer()  # for making data look normally-distributed\n",
    "    box = machine(box_model, ys)\n",
    "    z = transform(box, ys)\n",
    "\n",
    "    ridge_model = model.ridge_model ###\n",
    "    ridge =machine(ridge_model, W, z)\n",
    "    zhat = predict(ridge, W)\n",
    "\n",
    "    yhat = inverse_transform(box, zhat)\n",
    "    fit!(yhat, verbosity=0)\n",
    "    \n",
    "    return yhat\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The line marked `###`, where the new exported model's hyperparameter `ridge_model` is spliced into the network, is the only modification.\n",
    "\n",
    "This completes the export process.\n",
    "\n",
    "> **What's going on here?** MLJ's machine interface is built atop a more primitive *[model](adding_models_for_general_use.md)* interface, implemented for each algorithm. Each supervised model type (eg, `RidgeRegressor`) requires model `fit` and `predict` methods, which are called by the corresponding machine `fit!` and `predict` methods. We don't need to define a  model `predict` method here because MLJ provides a fallback which simply calls the node returned by `fit` on the data supplied: `MLJ.predict(model::Supervised{Node}, Xnew) = yhat(Xnew)`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's now let's wrap our composite model as a tuned model and evaluate on the Boston dataset:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "WrappedRidge(ridge_model = \u001b[0m\u001b[1mRidgeRegressor @ 1…11\u001b[22m,)\u001b[0m\u001b[1m @ 1…82\u001b[22m"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "task = load_boston()\n",
    "X, y = task()\n",
    "train, test = partition(eachindex(y), 0.7)\n",
    "wrapped_model = WrappedRidge(ridge_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(ridge_model = (target_type = Float64,\n",
       "                lambda = 0.01,),)"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params(wrapped_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(ridge_model = (lambda = \u001b[0m\u001b[1mNumericRange{lambda} @ 1…79\u001b[22m,),)"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nested_ranges = (ridge_model = (lambda = range(ridge_model, :lambda, lower=0.1, upper=100.0, scale=:log10),),)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "tuned_wrapped_model = TunedModel(model=wrapped_model, tuning=Grid(resolution=20),\n",
    "resampling=CV(), measure=rms, nested_ranges=nested_ranges);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6.88236977264247"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuned_wrapped = machine(tuned_wrapped_model, X, y)\n",
    "evaluate!(tuned_wrapped, resampling=Holdout(fraction_train=0.7), measure=rms, verbosity=0) |> mean  # nested resampling estimate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 1.1.0",
   "language": "julia",
   "name": "julia-1.1"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.1.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
